package com.cmw.auntapp.service;

import android.app.Notification;
import android.app.NotificationChannel;
import android.app.NotificationManager;
import android.app.Service;
import android.content.Context;
import android.content.Intent;
import android.graphics.Color;
import android.media.MediaPlayer;
import android.os.Binder;
import android.os.IBinder;
import android.os.PowerManager;
import android.util.Log;
import com.amap.api.location.AMapLocation;
import com.amap.api.location.AMapLocationClient;
import com.amap.api.location.AMapLocationClientOption;
import com.amap.api.location.AMapLocationListener;
import com.cmw.auntapp.R;
import com.cmw.auntapp.constant.CommandType;
import com.cmw.auntapp.constant.Constant;
import com.cmw.auntapp.core.base.IBaseView;
import com.cmw.auntapp.core.base.vo.DataResult;
import com.cmw.auntapp.core.util.DateUtil;
import com.cmw.auntapp.core.util.MediaPlayerUtil;
import com.cmw.auntapp.core.util.SharedPreferencesUtil;
import com.cmw.auntapp.model.LocationModel;
import com.cmw.auntapp.presenter.LocationPresenter;

import java.text.SimpleDateFormat;
import java.util.Date;

import static com.cmw.auntapp.constant.Constant.AUNT_LOCATION_KEY;
import static com.cmw.auntapp.constant.Constant.AUNT_LOCATION_LAST_TIME_KEY;

/**
 * 高德后台定位Service
 * https://blog.csdn.net/weixin_38754349/article/details/104421700?utm_medium=distribute.pc_relevant_bbs_down.none-task--2~all~first_rank_v2~rank_v29-1.nonecase&depth_1-utm_source=distribute.pc_relevant_bbs_down.none-task--2~all~first_rank_v2~rank_v29-1.nonecase
 * https://download.csdn.net/download/binbinxiaoz/10892551
 * 最终参考： https://blog.csdn.net/chaoyu168/article/details/88415631
 *          https://blog.csdn.net/qq_24536171/article/details/66971071?utm_medium=distribute.pc_relevant.none-task-blog-2%7Edefault%7EBlogCommendFromMachineLearnPai2%7Edefault-4.control&depth_1-utm_source=distribute.pc_relevant.none-task-blog-2%7Edefault%7EBlogCommendFromMachineLearnPai2%7Edefault-4.control
 * 高德定位：
 * https://www.jianshu.com/p/71aef60f4676
 * https://gitee.com/wonderful12/location-android?_from=gitee_search
 * 持续定位：
 * https://github.com/amapapi/LocationService
 */
public class LocationService extends Service implements AMapLocationListener, IBaseView {
    private static final String TAG = "LocationService";
    //    // 定位相关
//    private LocationClient mLocClient;
//    //
    private int msgId = -1;
    private PowerManager.WakeLock wakeLock = null;

    //声明AMapLocationClient类对象
    private AMapLocationClient mLocationClient = null;
    private AMapLocationClientOption locationOption;
    private  AMapLocation location = null;
    private int mInterval = 10; // 10秒定位一次
    //android 8.0后台定位权限
    private static final String NOTIFICATION_CHANNEL_NAME = "BG_LOCTION";
    private NotificationManager notificationManager = null;
    boolean isCreateChannel = false;

    private static final long LOCATION_UPDATE_TIME = 60 * 3; // 每3分钟上传一次阿姨位置数据

    MediaPlayer mediaPlayer = null;

    private LocationBinder locationBinder = new LocationBinder();

    private LocationPresenter locationPresenter;

    @Override
    public void onCreate() {
        super.onCreate();
        startForeground(12123, buildNotification());
        locationPresenter = new LocationPresenter(this);
        initGaoDe();
    }

    private void initGaoDe() {
        //初始化定位
        mLocationClient = new AMapLocationClient(getApplicationContext());
        //设置定位回调监听
        mLocationClient.setLocationListener(this);
        locationOption = new AMapLocationClientOption();
        /**
         * 设置定位场景，目前支持三种场景（签到、出行、运动，默认无场景）
         */
//        locationOption.setLocationPurpose(AMapLocationClientOption.AMapLocationPurpose.Sport);
        //设置定位模式为AMapLocationMode.Device_Sensors，仅设备模式。
        locationOption.setLocationMode(AMapLocationClientOption.AMapLocationMode.Hight_Accuracy);
        locationOption.setOnceLocation(false);

        //获取最近3s内精度最高的一次定位结果：
        //设置setOnceLocationLatest(boolean b)接口为true，启动定位时SDK会返回最近3s内精度最高的一次定位结果。如果设置其为true，setOnceLocation(boolean b)接口也会被设置为true，反之不会，默认为false。
//        option.setOnceLocationLatest(true);
        //设置定位间隔,单位毫秒,默认为2000ms，最低1000ms。
        locationOption.setInterval(1000*mInterval);
        //设置是否返回地址信息（默认返回地址信息）
        locationOption.setNeedAddress(true);
        //设置是否允许模拟位置,默认为true，允许模拟位置
        locationOption.setMockEnable(true);
        locationOption.setGpsFirst(true);
        //单位是毫秒，默认30000毫秒，建议超时时间不要低于8000毫秒。
        locationOption.setHttpTimeOut(50000);
        //关闭缓存机制
        locationOption.setLocationCacheEnable(false);
        if (null != mLocationClient && mInterval != 0) {
            mLocationClient.setLocationOption(locationOption);
            //设置场景模式后最好调用一次stop，再调用start以保证场景模式生效
            mLocationClient.stopLocation();
            mLocationClient.startLocation();
        }
    }



    //
    @Override
    public int onStartCommand(Intent intent, int flags, int startId) {
        if (intent != null) {
            msgId = intent.getIntExtra("msgId", -1);
        }
        flags = START_STICKY;
        setAppBackgroundPlayer();
        acquireWakeLock();
        // 刷新定位
        if (mLocationClient != null && mLocationClient.isStarted()) {
            mLocationClient.startLocation();
        }
        return super.onStartCommand(intent, flags, startId);
    }

    @Override
    public void onLocationChanged(AMapLocation loc) {
        if (loc == null) {
            Log.i(TAG, "amapLocation is null!");
            return;
        }
        if (loc.getErrorCode() != 0) {
            Log.i(TAG, "amapLocation has exception errorCode:" + loc.getErrorCode());
            return;
        }
        showLocationInfo(loc);
    }

    private void showLocationInfo(AMapLocation amapLocation) {
        // pringLocationInfo(amapLocation);
        new Thread(()-> asyncUpdateData(amapLocation)).start();
    }

    private void pringLocationInfo(AMapLocation amapLocation) {
        //定位成功回调信息，设置相关消息
        //存入数据库
        SimpleDateFormat df = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
        Date date = new Date(amapLocation.getTime());
        String time = df.format(date);
        Log.i(TAG,"当前定位时间-----"+time+", 当前实际时间："+ DateUtil.dateFormatToStr(DateUtil.DATE_TIME_FORMAT2, new Date()));
        Log.i(TAG,"当前定位结果来源-----"+amapLocation.getLocationType());//获取当前定位结果来源，如网络定位结果，详见定位类型表
        Log.i(TAG,"纬度 ----------------"+amapLocation.getLatitude());//获取纬度
        Log.i(TAG,"经度-----------------"+amapLocation.getLongitude());//获取经度
        Log.i(TAG,"精度信息-------------"+amapLocation.getAccuracy());//获取精度信息
        Log.i(TAG,"地址-----------------"+amapLocation.getAddress());//地址，如果option中设置isNeedAddress为false，则没有此结果，网络定位结果中会有地址信息，GPS定位不返回地址信息。
        Log.i(TAG,"国家信息-------------"+amapLocation.getCountry());//国家信息
        Log.i(TAG,"省信息---------------"+amapLocation.getProvince());//省信息
        Log.i(TAG,"城市信息-------------"+amapLocation.getCity());//城市信息
        Log.i(TAG,"城区信息-------------"+amapLocation.getDistrict());//城区信息
        Log.i(TAG,"街道信息-------------"+amapLocation.getStreet());//街道信息
        Log.i(TAG,"街道门牌号信息-------"+amapLocation.getStreetNum());//街道门牌号信息
        Log.i(TAG,"城市编码-------------"+amapLocation.getCityCode());//城市编码
        Log.i(TAG,"地区编码-------------"+amapLocation.getAdCode());//地区编码
        Log.i(TAG,"当前定位点的信息-----"+amapLocation.getAoiName());//获取当前定位点的AOI信息
    }

    private void asyncUpdateData(AMapLocation amapLocation) {
        SharedPreferencesUtil util = SharedPreferencesUtil.getInstance(this);
        long currTime = new Date().getTime();
        if(!util.existKey(AUNT_LOCATION_KEY)) {
            locationPresenter.doSave(amapLocation);
            util.saveLong(AUNT_LOCATION_LAST_TIME_KEY, currTime);
        } else {
            long lastUpdateTime = util.getLong(AUNT_LOCATION_LAST_TIME_KEY);
            long resultTime = (currTime - lastUpdateTime) /1000; //转成秒
            if (resultTime >= LOCATION_UPDATE_TIME) { // 每超过10分钟更新一次
                locationPresenter.doSave(amapLocation);
                util.saveLong(AUNT_LOCATION_LAST_TIME_KEY, currTime);
            }
        }
//        locationPresenter.doSave(locationModel);
//        util.saveLong(AUNT_LOCATION_LAST_TIME_KEY, currTime);
    }

    /**
     * 获取时间
     *
     * @return
     */
    public String getTime() {
        SimpleDateFormat formatter = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss ");
        Date curDate = new Date(System.currentTimeMillis());//获取当前时间
        String str = formatter.format(curDate);
        return str;
    }


    @Override
    public void onDestroy() {
        super.onDestroy();
        releaseWakeLock();
        if (mLocationClient != null) {
            mLocationClient.unRegisterLocationListener(this);
            mLocationClient.stopLocation();//停止定位后，本地定位服务并不会被销毁
            mLocationClient.onDestroy();//销毁定位客户端，同时销毁本地定位服务。
        }
        pausePlayer();
    }

    /**
     * 位置数据Binder
     */
    public class LocationBinder extends Binder {
        /**
         * 更新阿姨位置数据
         */
        public void updateLocation() {
            Log.i(TAG, "通过 LocationBinder 更新阿姨位置数据...");
            locationPresenter.doSave();
        }
    }

    @Override
    public IBinder onBind(Intent intent) {
        return locationBinder;
    }

    /**
     * PARTIAL_WAKE_LOCK:保持CPU 运转，屏幕和键盘灯有可能是关闭的。
     * SCREEN_DIM_WAKE_LOCK：保持CPU 运转，允许保持屏幕显示但有可能是灰的，允许关闭键盘灯
     * SCREEN_BRIGHT_WAKE_LOCK：保持CPU 运转，允许保持屏幕高亮显示，允许关闭键盘灯
     * FULL_WAKE_LOCK：保持CPU 运转，保持屏幕高亮显示，键盘灯也保持亮度
     * ACQUIRE_CAUSES_WAKEUP：强制使屏幕亮起，这种锁主要针对一些必须通知用户的操作.
     * ON_AFTER_RELEASE：当锁被释放时，保持屏幕亮起一段时间
     */
    private void acquireWakeLock() {
        if (null == wakeLock) {
            PowerManager pm = (PowerManager) getSystemService(Context.POWER_SERVICE);
            wakeLock = pm.newWakeLock(PowerManager.PARTIAL_WAKE_LOCK
                    | PowerManager.ON_AFTER_RELEASE, getClass()
                    .getCanonicalName());
            if (null != wakeLock) {
                //   Log.i(TAG, "call acquireWakeLock");
                Log.d("33333", "call acquireWakeLock");
                wakeLock.acquire();
            }
        }
    }

    private Notification buildNotification() {

        Notification.Builder builder = null;
        Notification notification = null;
        if (android.os.Build.VERSION.SDK_INT >= 26) {
            //Android O上对Notification进行了修改，如果设置的targetSDKVersion>=26建议使用此种方式创建通知栏
            if (null == notificationManager) {
                notificationManager = (NotificationManager) getSystemService(Context.NOTIFICATION_SERVICE);
            }
            String channelId = getPackageName();
            if (!isCreateChannel) {
                NotificationChannel notificationChannel = new NotificationChannel(channelId,
                        NOTIFICATION_CHANNEL_NAME, NotificationManager.IMPORTANCE_HIGH);
                notificationChannel.enableLights(false);//是否在桌面icon右上角展示小圆点
                notificationChannel.setLightColor(Color.BLUE); //小圆点颜色
                notificationChannel.setShowBadge(true); //是否在久按桌面图标时显示此渠道的通知
                notificationManager.createNotificationChannel(notificationChannel);
                isCreateChannel = true;
            }
            builder = new Notification.Builder(getApplicationContext(), channelId);
        } else {
            builder = new Notification.Builder(getApplicationContext());
        }
        builder.setSmallIcon(R.mipmap.ic_launcher)
                .setContentTitle("后台定位服务")
                .setContentText("")
                .setWhen(System.currentTimeMillis());
        if (android.os.Build.VERSION.SDK_INT >= 16) {
            notification = builder.build();
        } else {
            return builder.getNotification();
        }
        return notification;
    }
    // 释放设备电源锁
    private void releaseWakeLock() {
        if (null != wakeLock && wakeLock.isHeld()) {
            Log.d("33333", "call releaseWakeLock");
            //   Log.i(TAG, "call releaseWakeLock");
            wakeLock.release();
            wakeLock = null;
        }
    }
    /**
     * 设置应用进入后台，播放音频来进行cpu不休眠，进行应用保活
     */
    private void setAppBackgroundPlayer() {
        mediaPlayer = MediaPlayerUtil.playerMusic(this, R.raw.no_sound, true);
    }
    private void pausePlayer() {
        if (null == mediaPlayer) {
            Log.e(TAG, "mediaPlayer对象为空,无法停止无声音乐播放");
            return;
        }
        MediaPlayerUtil.releaseMediaPlayer(mediaPlayer);
    }

    @Override
    public boolean success(CommandType commandType, DataResult dataResult) {

        return false;
    }

    @Override
    public boolean failure(CommandType commandType, DataResult dataResult) {
        return false;
    }
}